"""
AI自动开发 - 环境管理服务层
负责Python包管理、虚拟环境操作
"""

import os
import sys
import subprocess
from pathlib import Path
from typing import Dict, List, Any, Optional
import json
import platform

from utils import format_timestamp, handle_errors


class EnvironmentService:
    """环境管理服务类"""

    def __init__(self):
        self.system = platform.system().lower()
        self.is_windows = self.system == 'windows'

    def _get_venv_paths(self, project_path: str) -> Dict[str, Path]:
        """获取虚拟环境相关路径"""
        project_dir = Path(project_path)
        venv_dir = project_dir / "venv"

        if self.is_windows:
            python_exe = venv_dir / "Scripts" / "python.exe"
            pip_exe = venv_dir / "Scripts" / "pip.exe"
            activate_script = venv_dir / "Scripts" / "activate.bat"
        else:
            python_exe = venv_dir / "bin" / "python"
            pip_exe = venv_dir / "bin" / "pip"
            activate_script = venv_dir / "bin" / "activate"

        return {
            'venv_dir': venv_dir,
            'python_exe': python_exe,
            'pip_exe': pip_exe,
            'activate_script': activate_script
        }

    def _run_pip_command(self, project_path: str, pip_args: List[str], timeout: int = 120) -> Dict[str, Any]:
        """在虚拟环境中运行pip命令"""
        try:
            paths = self._get_venv_paths(project_path)

            if not paths['venv_dir'].exists():
                return {
                    'success': False,
                    'message': '虚拟环境不存在，请先初始化项目'
                }

            if not paths['pip_exe'].exists():
                return {
                    'success': False,
                    'message': '虚拟环境中pip不存在'
                }

            # 构造pip命令
            cmd = [str(paths['pip_exe'])] + pip_args

            # 执行命令
            result = subprocess.run(
                cmd,
                cwd=project_path,
                capture_output=True,
                text=True,
                timeout=timeout,
                encoding='utf-8'
            )

            return {
                'success': result.returncode == 0,
                'returncode': result.returncode,
                'stdout': result.stdout,
                'stderr': result.stderr,
                'command': ' '.join(cmd)
            }

        except subprocess.TimeoutExpired:
            return {
                'success': False,
                'message': f'命令执行超时 ({timeout}秒)'
            }
        except Exception as e:
            return {
                'success': False,
                'message': f'执行pip命令失败: {str(e)}'
            }

    def _log_package_operation(self, project_path: str, operation: str, package_name: str, details: str = ""):
        """记录包管理操作到项目日志"""
        try:
            from project_service import project_service
            summary = f"{operation} {package_name}"
            if details:
                summary += f" - {details}"
            project_service.log_file_change(project_path, 'requirements.txt', 'PACKAGE', summary)
        except Exception:
            pass

    # ===== 包管理功能 =====

    def install_package(self, project_path: str, package_name: str, version: str = None) -> Dict[str, Any]:
        """
        在项目虚拟环境中安装Python包

        参数:
        - project_path: 项目路径
        - package_name: 包名
        - version: 版本号（可选）

        返回:
        - dict: 安装结果
        """
        try:
            # 构造包名（带版本）
            if version:
                package_spec = f"{package_name}=={version}"
            else:
                package_spec = package_name

            # 执行安装
            result = self._run_pip_command(project_path, ['install', package_spec])

            if result['success']:
                # 更新requirements.txt
                self._update_requirements_file(project_path)

                # 记录日志
                version_info = f"版本 {version}" if version else "最新版本"
                self._log_package_operation(project_path, '安装包', package_name, version_info)

                return {
                    'success': True,
                    'message': f'成功安装包: {package_spec}',
                    'package_name': package_name,
                    'version': version,
                    'stdout': result['stdout']
                }
            else:
                return {
                    'success': False,
                    'message': f'安装包失败: {package_spec}',
                    'error': result.get('stderr', result.get('message', '未知错误')),
                    'stdout': result.get('stdout', '')
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'安装包异常: {str(e)}'
            }

    def uninstall_package(self, project_path: str, package_name: str) -> Dict[str, Any]:
        """
        从项目虚拟环境中卸载Python包

        参数:
        - project_path: 项目路径
        - package_name: 包名

        返回:
        - dict: 卸载结果
        """
        try:
            # 执行卸载
            result = self._run_pip_command(project_path, ['uninstall', package_name, '-y'])

            if result['success']:
                # 更新requirements.txt
                self._update_requirements_file(project_path)

                # 记录日志
                self._log_package_operation(project_path, '卸载包', package_name)

                return {
                    'success': True,
                    'message': f'成功卸载包: {package_name}',
                    'package_name': package_name,
                    'stdout': result['stdout']
                }
            else:
                return {
                    'success': False,
                    'message': f'卸载包失败: {package_name}',
                    'error': result.get('stderr', result.get('message', '未知错误')),
                    'stdout': result.get('stdout', '')
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'卸载包异常: {str(e)}'
            }

    def upgrade_package(self, project_path: str, package_name: str) -> Dict[str, Any]:
        """
        升级项目虚拟环境中的Python包

        参数:
        - project_path: 项目路径
        - package_name: 包名

        返回:
        - dict: 升级结果
        """
        try:
            # 执行升级
            result = self._run_pip_command(project_path, ['install', '--upgrade', package_name])

            if result['success']:
                # 更新requirements.txt
                self._update_requirements_file(project_path)

                # 记录日志
                self._log_package_operation(project_path, '升级包', package_name)

                return {
                    'success': True,
                    'message': f'成功升级包: {package_name}',
                    'package_name': package_name,
                    'stdout': result['stdout']
                }
            else:
                return {
                    'success': False,
                    'message': f'升级包失败: {package_name}',
                    'error': result.get('stderr', result.get('message', '未知错误')),
                    'stdout': result.get('stdout', '')
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'升级包异常: {str(e)}'
            }

    def list_installed_packages(self, project_path: str) -> Dict[str, Any]:
        """
        列出项目虚拟环境中已安装的包

        参数:
        - project_path: 项目路径

        返回:
        - dict: 已安装包列表
        """
        try:
            # 执行list命令
            result = self._run_pip_command(project_path, ['list', '--format=json'])

            if result['success']:
                try:
                    packages_data = json.loads(result['stdout'])

                    # 整理包信息
                    packages = []
                    for pkg in packages_data:
                        packages.append({
                            'name': pkg['name'],
                            'version': pkg['version']
                        })

                    return {
                        'success': True,
                        'packages_count': len(packages),
                        'packages': packages
                    }

                except json.JSONDecodeError:
                    # JSON解析失败，使用文本格式
                    result_text = self._run_pip_command(project_path, ['list'])
                    return {
                        'success': True,
                        'packages_text': result_text.get('stdout', ''),
                        'message': '包列表获取成功（文本格式）'
                    }
            else:
                return {
                    'success': False,
                    'message': '获取包列表失败',
                    'error': result.get('stderr', result.get('message', '未知错误'))
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'获取包列表异常: {str(e)}'
            }

    def install_from_requirements(self, project_path: str, requirements_file: str = "requirements.txt") -> Dict[
        str, Any]:
        """
        从requirements.txt安装包

        参数:
        - project_path: 项目路径
        - requirements_file: requirements文件名

        返回:
        - dict: 安装结果
        """
        try:
            project_dir = Path(project_path)
            req_file_path = project_dir / requirements_file

            if not req_file_path.exists():
                return {
                    'success': False,
                    'message': f'requirements文件不存在: {requirements_file}'
                }

            # 执行安装
            result = self._run_pip_command(project_path, ['install', '-r', requirements_file], timeout=300)

            if result['success']:
                # 记录日志
                self._log_package_operation(project_path, '批量安装', requirements_file, '从requirements.txt安装')

                return {
                    'success': True,
                    'message': f'成功从 {requirements_file} 安装包',
                    'requirements_file': requirements_file,
                    'stdout': result['stdout']
                }
            else:
                return {
                    'success': False,
                    'message': f'从 {requirements_file} 安装失败',
                    'error': result.get('stderr', result.get('message', '未知错误')),
                    'stdout': result.get('stdout', '')
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'批量安装异常: {str(e)}'
            }

    def _update_requirements_file(self, project_path: str):
        """更新requirements.txt文件"""
        try:
            # 生成新的requirements.txt
            result = self._run_pip_command(project_path, ['freeze'])

            if result['success']:
                project_dir = Path(project_path)
                req_file_path = project_dir / 'requirements.txt'

                # 过滤掉一些系统包
                lines = result['stdout'].strip().split('\n')
                filtered_lines = []

                for line in lines:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        # 过滤一些不需要的包
                        package_name = line.split('==')[0].lower()
                        if package_name not in ['pip', 'setuptools', 'wheel']:
                            filtered_lines.append(line)

                # 写入文件
                content = '\n'.join(filtered_lines) + '\n'
                req_file_path.write_text(content, encoding='utf-8')

        except Exception:
            # 更新requirements.txt失败不影响主要操作
            pass

    def generate_requirements_file(self, project_path: str) -> Dict[str, Any]:
        """
        手动生成requirements.txt文件

        参数:
        - project_path: 项目路径

        返回:
        - dict: 生成结果
        """
        try:
            # 获取已安装包
            result = self._run_pip_command(project_path, ['freeze'])

            if result['success']:
                project_dir = Path(project_path)
                req_file_path = project_dir / 'requirements.txt'

                # 处理输出内容
                content = result['stdout'].strip()
                lines = content.split('\n')

                # 过滤和整理
                filtered_lines = []
                for line in lines:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        package_name = line.split('==')[0].lower()
                        if package_name not in ['pip', 'setuptools', 'wheel']:
                            filtered_lines.append(line)

                # 添加头注释
                final_content = f"# Requirements generated on {format_timestamp()}\n"
                final_content += f"# Python {sys.version.split()[0]}\n\n"
                final_content += '\n'.join(filtered_lines) + '\n'

                # 写入文件
                req_file_path.write_text(final_content, encoding='utf-8')

                # 记录日志
                self._log_package_operation(project_path, '生成', 'requirements.txt', f'{len(filtered_lines)} 个包')

                return {
                    'success': True,
                    'message': 'requirements.txt 生成成功',
                    'file_path': str(req_file_path),
                    'packages_count': len(filtered_lines),
                    'content': final_content
                }
            else:
                return {
                    'success': False,
                    'message': '生成requirements.txt失败',
                    'error': result.get('stderr', result.get('message', '未知错误'))
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'生成requirements.txt异常: {str(e)}'
            }

    def get_package_info(self, project_path: str, package_name: str) -> Dict[str, Any]:
        """
        获取包详细信息

        参数:
        - project_path: 项目路径
        - package_name: 包名

        返回:
        - dict: 包信息
        """
        try:
            # 执行show命令
            result = self._run_pip_command(project_path, ['show', package_name])

            if result['success']:
                return {
                    'success': True,
                    'package_name': package_name,
                    'info': result['stdout']
                }
            else:
                return {
                    'success': False,
                    'message': f'获取包信息失败: {package_name}',
                    'error': result.get('stderr', result.get('message', '包不存在'))
                }

        except Exception as e:
            return {
                'success': False,
                'message': f'获取包信息异常: {str(e)}'
            }

    def check_venv_status(self, project_path: str) -> Dict[str, Any]:
        """
        检查虚拟环境状态

        参数:
        - project_path: 项目路径

        返回:
        - dict: 虚拟环境状态
        """
        try:
            paths = self._get_venv_paths(project_path)

            status = {
                'venv_exists': paths['venv_dir'].exists(),
                'python_exists': paths['python_exe'].exists(),
                'pip_exists': paths['pip_exe'].exists(),
                'venv_path': str(paths['venv_dir'])
            }

            if status['python_exists']:
                # 获取Python版本
                try:
                    result = subprocess.run(
                        [str(paths['python_exe']), '--version'],
                        capture_output=True,
                        text=True,
                        timeout=10
                    )
                    if result.returncode == 0:
                        status['python_version'] = result.stdout.strip()
                except:
                    pass

            if status['pip_exists']:
                # 获取pip版本
                try:
                    result = subprocess.run(
                        [str(paths['pip_exe']), '--version'],
                        capture_output=True,
                        text=True,
                        timeout=10
                    )
                    if result.returncode == 0:
                        status['pip_version'] = result.stdout.strip()
                except:
                    pass

            return {
                'success': True,
                'status': status
            }

        except Exception as e:
            return {
                'success': False,
                'message': f'检查虚拟环境状态异常: {str(e)}'
            }


# 全局实例
environment_service = EnvironmentService()

# 测试代码
if __name__ == "__main__":
    # 测试环境服务
    test_project = "./test_project"

    print("环境服务测试:")

    # 检查虚拟环境状态
    status = environment_service.check_venv_status(test_project)
    print(f"虚拟环境状态: {status}")

    # 获取已安装包列表
    packages = environment_service.list_installed_packages(test_project)
    print(f"已安装包数量: {packages.get('packages_count', 0)}")